package com.base

import android.bluetooth.BluetoothGatt
import android.content.Context
import android.os.Handler
import android.os.Message
import android.util.Log
import com.clj.fastble.BleManager
import com.clj.fastble.callback.BleGattCallback
import com.clj.fastble.callback.BleNotifyCallback
import com.clj.fastble.callback.BleReadCallback
import com.clj.fastble.data.BleDevice
import com.clj.fastble.exception.BleException
import com.orhanobut.logger.Logger
import com.somlsis.bean.Device
import com.somlsis.bean.DeviceInfo
import com.somlsis.bean.Motion
import com.somlsis.bean.UserLatLng
import com.utils.ByteUtils
import com.utils.StringUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch


class DeviceCenter {

    private lateinit var context: Context
    lateinit var bleManager: BleManager
    private var listener: OnStrideListener? = null

    private var motionState = DeviceConfig.MOTION_STATE_SUSPEND
    private var motionTime: Long = 0
    private var totalDistance: Long = 0
    private var motionList = ArrayList<Motion>()
    private var latLngs = ArrayList<UserLatLng>()
    private var timeHandle: Handler? = null

    interface OnStrideListener {
        //isRun 是否是跑步,speed 速度 frequency 步频 stride步幅 distance总距离
        fun onStride(
            isRun: Boolean,
            speed: String,
            frequency: Float,
            stride: Float,
            distance: Float,
            motionTime: Long,
            motionList: ArrayList<Motion>
        )
    }

    companion object {
        val instance = DeviceCenterInit.init
    }

    private object DeviceCenterInit {
        val init = DeviceCenter()
    }

    fun initOther(context: Context) {
        this.context = context
        bleManager = BleManager.getInstance()
    }

    fun connectDevice(device: Device) {
        bleManager.connect(device, object : BleGattCallback() {
            override fun onStartConnect() {
            }

            override fun onConnectFail(
                bleDevice: BleDevice?,
                exception: BleException?
            ) {

            }

            override fun onConnectSuccess(
                bleDevice: BleDevice?,
                gatt: BluetoothGatt?,
                status: Int
            ) {
                registerNotification(bleDevice)

            }

            override fun onDisConnected(
                isActiveDisConnected: Boolean,
                device: BleDevice?,
                gatt: BluetoothGatt?,
                status: Int
            ) {

            }

        })
    }

    fun registerNotification(bleDevice: BleDevice?) {
        bleDevice?.let { ble ->
            bleManager.notify(
                ble,
                DeviceConfig.RUNNING_SPEED_AN_CADENCE_UUID,
                DeviceConfig.RSC_MEASUREMENT_UUID,
                object : BleNotifyCallback() {
                    override fun onNotifySuccess() {
                        Logger.d("onNotifySuccess")
                    }

                    override fun onNotifyFailure(exception: BleException?) {
                        Logger.d("onNotifyFailure：" + exception.toString())
                    }

                    override fun onCharacteristicChanged(data: ByteArray?) {
                        data?.let { it ->
                            var isRun = ByteUtils.getByteToBoolean(it[0])

                            var speed = ByteUtils.getByteToInt(it[1], it[2]) / 256f
                            var frequency = ByteUtils.getByteToInt(it[3]) * 2
                            var stride = ByteUtils.getByteToInt(it[4], it[5]) / 2f
                            var distance =
                                ByteUtils.getByteToInt(it[6], it[7], it[8], it[9]) / 10000f
                            Log.d("data", "isRun:$isRun")
                            Log.d("data", "速度:$speed")
                            Log.d("data", "步频:$frequency")
                            Log.d("data", "幅度:$stride")
                            Log.d("data", "总距离:$distance")
                            var stepNum = (totalDistance / stride).toLong()
                            var serialNum = ble.mac
                            if (motionState == DeviceConfig.MOTION_STATE_RUNNING) {
                                val motionData = Motion(
                                    1000,
                                    "全掌",
                                    serialNum,
                                    0.5f,
                                    speed,
                                    motionTime,
                                    stride,
                                    stepNum,
                                    frequency,
                                    totalDistance
                                )
                                motionList.add(motionData)
                            }
                            listener?.let {
                                it.onStride(
                                    isRun,
                                    StringUtils.getPace(speed),
                                    frequency,
                                    stride,
                                    distance,
                                    motionTime,
                                    motionList
                                )
                            }
                        }
                    }
                })
        }

    }

    fun getDeviceCenterInfo(bleDevice: BleDevice?, callback: onDeviceInfoCallBack) {
        bleDevice?.let {
            val coroutineScope = CoroutineScope(Dispatchers.IO)
            coroutineScope.launch {
                var modelNumber = ""//设备号
                var serialNumber = ""//序列号
                var hardwareRevision = "" //硬件版本
                var firmwareRevision = "" //固件版本
                var softwareRevision = ""//软件版本
                bleManager.read(
                    bleDevice,
                    DeviceConfig.DEVICE_INFORMATION_UUID,
                    DeviceConfig.MODEL_NUMBER_UUID,
                    object : BleReadCallback() {
                        override fun onReadSuccess(data: ByteArray?) {
                            data?.let {
                                modelNumber = String(data)
                            }
                        }

                        override fun onReadFailure(exception: BleException?) {
                        }

                    })
                bleManager.read(
                    bleDevice,
                    DeviceConfig.DEVICE_INFORMATION_UUID,
                    DeviceConfig.SERIAL_NUMBER_UUID,
                    object : BleReadCallback() {
                        override fun onReadSuccess(data: ByteArray?) {
                            data?.let {
                                serialNumber = String(data)
                            }
                        }

                        override fun onReadFailure(exception: BleException?) {
                        }

                    })
                bleManager.read(
                    bleDevice,
                    DeviceConfig.DEVICE_INFORMATION_UUID,
                    DeviceConfig.HARDWARE_REVISION_UUID,
                    object : BleReadCallback() {
                        override fun onReadSuccess(data: ByteArray?) {
                            data?.let {
                                hardwareRevision = String(data)
                            }
                        }

                        override fun onReadFailure(exception: BleException?) {
                        }

                    })
                bleManager.read(
                    bleDevice,
                    DeviceConfig.DEVICE_INFORMATION_UUID,
                    DeviceConfig.FIRMWARE_REVISION_UUID,
                    object : BleReadCallback() {
                        override fun onReadSuccess(data: ByteArray?) {
                            data?.let {
                                firmwareRevision = String(data)
                            }
                        }

                        override fun onReadFailure(exception: BleException?) {
                        }

                    })
                bleManager.read(
                    bleDevice,
                    DeviceConfig.DEVICE_INFORMATION_UUID,
                    DeviceConfig.SOFTWARE_REVISION_UUID,
                    object : BleReadCallback() {
                        override fun onReadSuccess(data: ByteArray?) {
                            data?.let {
                                softwareRevision = String(data)
                            }
                        }

                        override fun onReadFailure(exception: BleException?) {
                        }

                    })
                while (modelNumber == null ||
                    serialNumber == null || hardwareRevision == null || firmwareRevision == null || softwareRevision == null
                ) {
                    delay(1000)
                }

                val deviceInfo = DeviceInfo()
                deviceInfo.serial_name = it.name
                deviceInfo.serial_mac = it.mac
                deviceInfo.serial_type = modelNumber
                deviceInfo.serial_num = modelNumber
                deviceInfo.serial_version = firmwareRevision
                deviceInfo.serial_version = hardwareRevision
                callback.deviceInfoCallBack(deviceInfo)
            }


        }
    }

    fun setOnStrideListener(onStrideListener: OnStrideListener) {
        listener = onStrideListener
    }

    /**
     *  {"tot_len": '里程',
     *  "step_len": '步长',
     *  "step_rate": "步频",
     *  "speed": "配速",
     *  "ground_time": "触地时间",
     *  "sky_rate": "腾空比",
     *  "ground_type": "触地类型",
     *  "step_num": "布数",
     *  "sport_time": "运动时间",
     *  "serial_num": "产品序列号"}
     * */


    fun startRunning() {
        motionList = ArrayList()
        latLngs = ArrayList()
        totalDistance = 0
        motionTime = 0
        timeHandle = object : Handler(context.mainLooper) {
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)

                if (motionState == DeviceConfig.MOTION_STATE_RUNNING) {
                    motionTime += 1000
                    sendEmptyMessageDelayed(0, 1000)
                } else if (motionState == DeviceConfig.MOTION_STATE_SUSPEND) {
                    sendEmptyMessageDelayed(0, 1000)
                } else {
                    removeCallbacksAndMessages(null)
                }
            }
        }
        timeHandle?.let {
            it.sendEmptyMessage(0)
        }
    }

    fun addLatLng(latLng: UserLatLng) {
        if (motionState == DeviceConfig.MOTION_STATE_RUNNING) {
            latLngs.add(latLng)
        }
    }

    fun pauseRunning() {
        motionState = if (motionState == DeviceConfig.MOTION_STATE_RUNNING)
            DeviceConfig.MOTION_STATE_SUSPEND
        else DeviceConfig.MOTION_STATE_RUNNING

    }

    fun getMotionState(): Int {
        return motionState
    }

    fun stopRunning(): ArrayList<Motion> {
        motionState = DeviceConfig.MOTION_STATE_STOP
        return motionList
    }

    fun getLatLngs(): ArrayList<UserLatLng> {
        return latLngs
    }


    fun onDestroy() {
        timeHandle?.let {
            it.removeCallbacksAndMessages(null)
        }
    }

    interface onDeviceInfoCallBack {
        fun deviceInfoCallBack(deviceInfo: DeviceInfo)
    }
}